package cn.blu10ph.trustshare.controller;

import cn.blu10ph.trustshare.bean.msg.FindNodeMsg;
import cn.blu10ph.trustshare.bean.node.NodeInfo;
import cn.blu10ph.trustshare.bean.node.TrustNode;
import cn.blu10ph.trustshare.constant.Constant;
import cn.blu10ph.trustshare.core.PGPManager;
import cn.blu10ph.trustshare.core.RoutingTable;
import cn.blu10ph.trustshare.core.ServiceCore;
import cn.blu10ph.trustshare.service.DHTMsgService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import java.util.*;

/**
 * <p> NodeController </p >
 *
 * @author cxx
 * @date 2024/4/10 23:23
 */
@Slf4j
@RestController
@RequestMapping("/node")
public class NodeController {

    @Resource
    RoutingTable routingTable;

    @Resource
    PGPManager pgpManager;

    @Resource
    ServiceCore serviceCore;

    @GetMapping(value = "/getList")
    public List<TrustNode> getList(String[] trustLevel, String nodeId) {
        log.info("Rest get node list:{},{}", trustLevel, nodeId);
        Set<String> trustLevels = new HashSet<>(Arrays.asList(trustLevel));
        Set<String> nodeIds = pgpManager.getNodeIdByTrustLevel(trustLevels);
        List<TrustNode> result;
        if(StringUtils.hasText(nodeId)){
            if(!ObjectUtils.isEmpty(trustLevels) && nodeIds.contains(nodeId)){
                TrustNode node = routingTable.getNodeById(nodeId);
                result = Collections.singletonList(node);
            } else {
                result = Collections.emptyList();
            }
        }else{
            log.info("Rest get node list nodes:{}", nodeIds);
            result = routingTable.getAllNodeList();
            if(!ObjectUtils.isEmpty(trustLevels)) {
                result = result.stream()
                        .filter(item -> nodeIds.contains(item.getNodeId()))
                        .toList();
            }
        }
        result.forEach(node->{
            node.setTrustLevel(pgpManager.getTrustLevel(node.getNodeId()));
            node.setActiveTime(serviceCore.getNodeActive(node.getNodeId()));
        });
        return result;
    }

    @PostMapping(value = "/add")
    public void add(@RequestBody NodeInfo nodeInfo) throws Exception {
        log.info("Rest add node:{}", nodeInfo);
        // send get_public_key by node
        serviceCore.sendGetPublicKey(nodeInfo);
    }

    @GetMapping(value = "/ping")
    public void ping(String id) throws Exception {
        log.info("Rest ping node:{}", id);
        DHTMsgService<Object> msgService = serviceCore.getMsgService(Constant.MSG_TYPE_PING);
        TrustNode node = serviceCore.getNode(id);
        msgService.sendQuery(node, null);
    }

    @GetMapping(value = "/find")
    public void find(String id) throws Exception {
        log.info("Rest find node:{}", id);
        DHTMsgService<Object> msgService = serviceCore.getMsgService(Constant.MSG_TYPE_FIND_NODE);
        List<TrustNode> nodeList = serviceCore.findNodeListById(id);
        for(TrustNode node : nodeList) {
            msgService.sendQuery(node, new FindNodeMsg(id));
        }
    }

}
